cardboard-vr-display
A JavaScript implementation of a WebVR 1.1 VRDisplay. This is the magic
behind rendering distorted stereoscopic views for browsers that do not support the WebVR API
with the webvr-polyfill.
Unless you're building a WebVR wrapper, you probably want to use webvr-polyfill directly
rather than this. This component does not polyfill interfaces like VRFrameData
and
navigator.getVRDisplays
, and up to the consumer, although trivial (see examples).
How It Works
As of 1.0.4, CardboardVRDisplay
uses RelativeOrientationSensor for orientation tracking,
falling back to DeviceMotionEvents using sensor fusion and pose prediction.
RelativeOrientationSensor is a new API (read more about the new Sensors on the web)
first implemented in Chrome M63. This API uses the new Feature Policy specification which allows
developers to selectively enable or disable browser features.
It can also render in stereo mode, and includes mesh-based
lens distortion. This display also includes user interface elements in VR mode
to make the VR experience more intuitive, including:
- A gear icon to select your VR viewer.
- A back button to exit VR mode.
- An interstitial which only appears in portrait orientation, requesting you switch
into landscape orientation (if orientation lock is not available).
iframes
By default, main frames and same-origin iframes have access to Sensor APIs,
but cross-origin iframes must specify feature policy and allow gyroscope
and
accelerometer
features. If your experience is attempting to use the native
WebXR Device API in an iframe, you'll have to specify that feature as well (WebXR's
feature name may change). All of these features require HTTPS to function, except for localhost
, where HTTP is allowed.
<iframe src="https://otherdomain.com" allow="gyroscope; accelerometer; xr"></iframe>
While devicemotion
is a fallback for Sensors, eventually devicemotion
will be behind the same
Feature Policy as Sensors and it is encouraged to adhere to these policies in the meantime.
If the Feature Policy for Sensors is denied, CardboardVRDisplay
will not always attempt
to fall back to devicemotion
. Using Feature Policies now will guarantee a more future-proof experience.
Caveats
- On iOS, cross-origin iframes do not have access to the
devicemotion
events.
The CardboardVRDisplay
however does respond to events passed in from a parent
frame via postMessage
. See the iframe example to see how
the events must be formatted. - Chrome M63 supports Sensors, although not the corresponding Feature Policy until Chrome M65.
This results in Chrome M63/M64 only supporting Sensors in main frames, and these browsers
will fall back to using devicemotion if in iframes.
- Using Sensors in a cross-origin iframe requires the frame to be in focus. In builds of Chrome prior to M69, this logic is erroneously reversed. If loading content via cross-origin iframe, you can disable Sensors, triggering the
devicemotion
fallback with this hacky workaround. More info in #27.
Magic Window
It is possible to have a magic window using a VRDisplay that isn't 100% width/height of the window, and can jump into fullscreen WebVR. See the magic window for usage.
Installation
$ npm install --save cardboard-vr-display
Browser Support
Should support most modern browsers (IE11 is missing a few, for example) and requires ES5 JavaScript support. If you want to support a non-ES5 browser, or browser lacking some DOM globals, you must use a transformation or provide polyfills to support older environments.
Globals required:
Additionally, WebGL support, devicemotion
events, and common browser globals (window
, navigator
, document
) are also required in the environment.
Usage
cardboard-vr-display
exposes a constructor for a CardboardVRDisplay
that takes
a single options configuration, detailed below. Check out running the demo
to try the different options.
import CardboardVRDisplay from 'cardboard-vr-display';
const options = {
ADDITIONAL_VIEWERS: [],
DEFAULT_VIEWER: '',
MOBILE_WAKE_LOCK: true,
DEBUG: false,
DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json',
K_FILTER: 0.98,
PREDICTION_TIME_S: 0.040,
CARDBOARD_UI_DISABLED: false,
ROTATE_INSTRUCTIONS_DISABLED: false,
YAW_ONLY: false,
BUFFER_SCALE: 0.5,
DIRTY_SUBMIT_FRAME_BINDINGS: false,
};
const display = new CardboardVRDisplay(options);
function MockVRFrameData () {
this.leftViewMatrix = new Float32Array(16);
this.rightViewMatrix = new Float32Array(16);
this.leftProjectionMatrix = new Float32Array(16);
this.rightProjectionMatrix = new Float32Array(16);
this.pose = null;
};
const frame = new (window.VRFrameData || MockVRFrameData)();
display.isConnected;
display.getFrameData(frame);
frame.rightViewMatrix;
frame.pose;
Development
npm install
: installs the dependencies.npm run build
: builds the distributable.npm run watch
: watches src/
for changes and rebuilds on change.
Releasing a new version
For maintainers only, to cut a new release for npm, use the [npm version] command. The preversion
, version
and postversion
npm scripts will run tests, build, add built files and tag to git, push to github, and publish the new npm version.
npm version <semverstring>
Running The Demo
View the example to see a demo running the CardboardVRDisplay. This executes
a minimal WebVR 1.1 polyfill and parses query params to inject configuration parameters.
View some premade links at index.html. For example, to set the buffer scale to 1.0
and limit rotation to yaw, go to [https://immersive-web.github.io/cardboard-vr-display/examples/index.html?YAW_ONLY=true&BUFFER_SCALE=1.0].
View all config options at src/options.js
.
License
This program is free software for both commercial and non-commercial use,
distributed under the Apache 2.0 License.